package com.cds.drizzt.controller;

import com.cds.drizzt.dao.UsersDao;
import com.cds.drizzt.entity.JsonResult;
import com.cds.drizzt.entity.Users;
import com.cds.drizzt.utils.JwtUtils;
import com.cds.drizzt.utils.Pbkdf2Encoder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.tags.Tags;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/auth")
@Slf4j
@Tags({
    @Tag(name = "登录注册", description = "用户登录注册接口") // 主标签，配合 @Operation 描述接口的操作
//    @Tag(name = "测试登录", description = "测试登录接口")    // 副标签，有多少个@Tag标签就会分出多少个重复组
    // tag标签主要用于接口分组，方便在Swagger UI中查看
})
public class LoginController {
    @Autowired
    private Pbkdf2Encoder pbkdf2Encoder;
    @Autowired
    private UsersDao usersDao;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private AuthenticationManager authenticationManager;

    @GetMapping("/test")
    @Operation(summary = "测试登录", description = "测试登录接口") // @Operation 用于描述接口的操作，summary 用于总结接口的功能，description 用于详细描述接口的功能
    public String testLogin() {
        return "test login";
    }

    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "用户注册接口") // @Operation 用于描述接口的操作，summary 用于总结接口的功能，description 用于详细描述接口的功能
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "注册成功"),
        @ApiResponse(responseCode = "400", description = "注册失败")
    })
    public JsonResult<String> register(@RequestBody Users users) {
        // 检查用户名是否已存在
        if (usersDao.getUserByUsername(users.getUsername()) != null) {
            return JsonResult.error(400, "用户名已存在");
        }

        // 注册逻辑
        users.setPassword(pbkdf2Encoder.encode(users.getPassword()));
        System.out.println("register: " + users.getPassword());
        users.setPassword(passwordEncoder.encode(users.getPassword()));
        // 插入用户到数据库
        usersDao.insert(users);
        return JsonResult.success("register success");
    }

    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录接口") // @Operation 用于描述接口的操作，summary 用于总结接口的功能，description 用于详细描述接口的功能
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "登录成功"),
        @ApiResponse(responseCode = "400", description = "登录失败")
    })
    public JsonResult<String> login(@RequestBody Map<String, String> loginRequest) {
        try {
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginRequest.get("username"),
                        loginRequest.get("password")
                )
            );
            // 检查authentication对象
            if (authentication != null) {
                SecurityContext context = SecurityContextHolder.getContext();
                context.setAuthentication(authentication);
                // 或者使用上面提到的创建空上下文的方法，如果context为null
                // SecurityContextHolder.setContext(context);
            }
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            String jwt = jwtUtils.generateJwtToken(userDetails);

            Map<String, String> response = new HashMap<>();
            response.put("token", jwt);
//            response.put("username", userDetails.getUsername());
            return JsonResult.success(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResult.error(400, "Authentication failed: " + e.getMessage());
        }
    }
}
